/*
* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

#ifndef B2_WORLD_CALLBACK_H
#define B2_WORLD_CALLBACK_H

#include "../Common/b2Settings.h"

struct b2Vec2;
struct b2XForm;
class  b2Fixture;
class  b2Body;
class  b2Joint;
class  b2Contact;
struct b2ContactPoint;
struct b2ContactResult;
struct b2Manifold;

// Joint and fixtures are destroyed when their associated body is destroyed.
// Implement this listener so than you may nullify reference to these joints and shapes.
class b2DestructionListener
{
public:
	~b2DestructionListener() {};

	// Called when any joint is about to be destroyed due to the destruction of on of its 
	// attached body.
	virtual void SayGoodbye(b2Joint* joint) = 0;
	
	// Called when any fixture is about to be destroyed due to the destruction of one of its
	// attached body.
	virtual void SayGoodbye(b2Fixture* fixture) = 0;
};

// This is called when a body's shape passes outside of the world boundary.
class b2BoundaryListener
{
public:
	virtual ~b2BoundaryListener() {};

	// This is called for each body that leave the world boundary.
	// @warning you can't modify the world inside the callback.
	virtual void Violation(b2Body* body) = 0; 
};

// Implement this class to provide collision filtering. In other world, you can implement 
// this class if you want finer control over contact creation.
class b2ContactFilter
{
public:
	// Return true if contact calculations should be performed between these two shapes.
	// @warning for performance reason, this is only called when the AABB begin to overlap.
	virtual bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB);

	// Return true if the given shape should be considered for ray intersection.
	virtual bool RayCollide(void* userData, b2Fixture* fixture);
};

// Contact impulse for reporting.Impulses are used instead of forces because
// sub-step forces may approch infinity for rigid body collision. These match up one-to-one with the
// Contact point in b2Manifold.
struct b2ContactImpulse
{
	float32 normalImpulses[b2_maxManifoldPoints];
	float32 tangentImpulses[b2_maxManifoldPoints];
};

// Implement this class to get contact information. You can use these results 
// for things like sounds and game logic.You can also get contacts results by 
// traversing the contact lists after the time step.However you might miss some 
// contacts because continuous physics leads to sub-stepping.
// Additionally you may receive multiple callbacks for the same contact in a single step.
// You should strive to make you callbacks more efficient,because there may be so many 
// callbacks per time step.
// @warning you can not create/destroy Box2D entity inside these callbacks.
class b2ContactListener
{
public:
	~b2ContactListener() {}

	// Called when two fixtures begin to touch.
	virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); }

	// Called when two fixtures cease to touch.
	virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); }

	// This is called after a contact is updated.This allow you to inspect a contact before it goes to the solver.
	// If you are careful, you can modify the contact manifold(e.g. disable contact.)
	// A copy of old manifold is provided so that you can detect changes.
	// Note: this is called only for awake bodies.
	// Note: this is called even the contact number is zero.
	// Note: this is not called for sensors.
	// Note: if you set the the number of contact number to zero,you will not get a 
	// EndContact callback, However you may get a begine contact the next step.
	virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
	{
		B2_NOT_USED(contact);
		B2_NOT_USED(oldManifold);
	}

	// This let you inspect a contact after the solver is finished.This is usefull for inspection impulses.
	// Note: the contact manifold does not include time of impact impact impulse, which can be arbitrarily large if
	// the sub-step is small.Hence the impulse is provided explicitly in a separate data structure.
	// Note: this is only called for contacts that are touching, solid and awake.
	virtual void PostSolve(const b2Contact* constact, const b2ContactImpulse* impulse)
	{
		B2_NOT_USED(constact);
		B2_NOT_USED(impulse);
	}
};

// Color for debug drawing. Each value is in range [0, 1].
struct b2Color
{
	b2Color() {}
	b2Color(float32 _r, float32 _g, float32 _b) : r(r), g(g), b(b) {}
	void Set(float32 _r, float32 _g, float32 _b) { r=_r; g=_g; b=_b; }
	float32 r, g, b;
};

// Implement and register this class with a b2Wold to provide debug draw of physics 
// entity in your game.
class b2DebugDraw
{
public:
	b2DebugDraw() : m_drawFlags(0) {}
	virtual ~b2DebugDraw() {}

	enum
	{
		e_shapeBit		= 0x0001,	// draw shapes.
		e_jointBit		= 0x0002,	// draw joint connection.
		e_coreShapeBit	= 0x0004,	// draw core (TOI) shapes.
		e_aabbBit		= 0x0008,	// draw axis aligned bounding box.
		e_obbBit		= 0x0010,	// draw oriented bounding box.
		e_pairBit		= 0x0020,	// draw broad-phase pairs.
		e_centerOfMassBit	= 0x0040, // draw center of mass frame.
		e_controllerBit	= 0x0080,	// draw controllers.
	};

	// Set the drawing flag.
	void SetFlags(uint32 flags) { m_drawFlags = flags; }

	// Get the drawing flags.
	uint32 GetFlags() const { return m_drawFlags; }

	// Append flags to current flags.
	void AppendFlags(uint32 flags) { m_drawFlags |= flags; }

	// Clear flags from the current flags.
	void ClearFlags(uint32 flags) { m_drawFlags &= ~flags; }

	// Draw a closed polygon provided in CCW order.
	virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0;

	// Draw a solid closed polygon provided in CCW order.
	virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0;

	// Draw a circle.
	virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) = 0;

	// Draw a solid circle.
	virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) = 0;

	// Draw a segment.
	virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0;

	// Draw a transform.Choose your own length scale.
	virtual void DrawXForm(const b2XForm& xf) = 0;

protected:
	uint32 m_drawFlags;
};

#endif
